#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
#include <ESP8266WiFi.h>
#include "ai_energy_analyzer.h"
#include "power_monitor.h"
#include "data_transmitter.h"

// 定义引脚
#define SD_CS_PIN 4
#define CURRENT_SENSOR_PIN A0
#define VOLTAGE_SENSOR_PIN A1
#define RELAY_PIN 2

// 初始化RTC
RTC_DS3231 rtc;

// 初始化电力监测器
PowerMonitor powerMonitor(CURRENT_SENSOR_PIN, VOLTAGE_SENSOR_PIN);

// 初始化数据传输器
DataTransmitter dataTransmitter;

// 初始化AI能源分析器
AIEnergyAnalyzer aiAnalyzer;

// WiFi配置
const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
  
  // 初始化I2C通信
  Wire.begin();
  
  // 初始化RTC
  if (!rtc.begin()) {
    Serial.println("无法初始化RTC模块！");
  }
  
  // 初始化SD卡
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("无法初始化SD卡！");
  }
  
  // 初始化电力监测器
  powerMonitor.init();
  
  // 初始化数据传输器
  dataTransmitter.init();
  
  // 初始化AI能源分析器
  aiAnalyzer.init();
  
  // 初始化WiFi
  WiFi.begin(ssid, password);
  Serial.print("连接WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("已连接！");
  
  // 初始化继电器
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
  
  // 记录系统启动信息
  logEvent("系统启动");
}

void loop() {
  // 读取电力数据
  PowerData powerData = powerMonitor.readData();
  
  // 添加时间戳
  DateTime now = rtc.now();
  powerData.timestamp = now.unixtime();
  
  // 使用AI分析器分析数据
  EnergyInsight insight = aiAnalyzer.analyze(powerData);
  
  // 根据分析结果执行优化控制
  executeOptimization(insight);
  
  // 记录数据
  logData(powerData);
  
  // 发送数据到服务器
  if (WiFi.status() == WL_CONNECTED) {
    dataTransmitter.sendData(powerData);
    if (insight.hasAnomaly || insight.hasRecommendation) {
      dataTransmitter.sendInsight(insight);
    }
  }
  
  // 显示当前状态
  displayStatus(powerData, insight);
  
  // 每分钟采集一次数据
  delay(60000);
}

void executeOptimization(EnergyInsight insight) {
  // 如果检测到异常用电，发出告警
  if (insight.hasAnomaly) {
    triggerAlarm(insight.anomalyType);
  }
  
  // 根据节能建议控制负载
  if (insight.hasRecommendation && insight.autoOptimize) {
    // 实际控制逻辑根据负载类型和建议内容而定
    if (insight.recommendationType == REDUCE_POWER) {
      digitalWrite(RELAY_PIN, LOW);
      logEvent("执行节能控制：关闭负载");
    }
  }
}

void logData(PowerData data) {
  // 记录数据到SD卡
  File dataFile = SD.open("energy_data.csv", FILE_WRITE);
  if (dataFile) {
    char dataString[100];
    sprintf(dataString, "%ld,%.2f,%.2f,%.2f,%.2f",
            data.timestamp, data.voltage, data.current, data.power, data.energy);
    dataFile.println(dataString);
    dataFile.close();
  }
}

void logEvent(String event) {
  // 记录事件到日志文件
  File logFile = SD.open("system.log", FILE_WRITE);
  if (logFile) {
    DateTime now = rtc.now();
    char timeString[20];
    sprintf(timeString, "%04d-%02d-%02d %02d:%02d:%02d",
            now.year(), now.month(), now.day(),
            now.hour(), now.minute(), now.second());
    logFile.print(timeString);
    logFile.print(": ");
    logFile.println(event);
    logFile.close();
    
    // 同时在串口打印
    Serial.print(timeString);
    Serial.print(": ");
    Serial.println(event);
  }
}

void triggerAlarm(int anomalyType) {
  // 触发本地告警
  // 发送告警信息到服务器
  String alarmMessage = "检测到异常用电：";
  switch (anomalyType) {
    case OVERLOAD:
      alarmMessage += "过载";
      break;
    case UNEXPECTED_USAGE:
      alarmMessage += "异常用电模式";
      break;
    case POWER_SURGE:
      alarmMessage += "电压浪涌";
      break;
  }
  logEvent(alarmMessage);
}

void displayStatus(PowerData data, EnergyInsight insight) {
  // 在LCD上显示当前状态
  // 此处简化，实际应根据LCD型号实现
  
  // 同时在串口打印当前状态
  Serial.println("--- 能源状态 ---");
  Serial.print("电压: ");
  Serial.print(data.voltage, 1);
  Serial.println(" V");
  Serial.print("电流: ");
  Serial.print(data.current, 2);
  Serial.println(" A");
  Serial.print("功率: ");
  Serial.print(data.power, 1);
  Serial.println(" W");
  Serial.print("电能: ");
  Serial.print(data.energy, 2);
  Serial.println(" kWh");
  
  if (insight.hasAnomaly) {
    Serial.print("异常: ");
    Serial.println(insight.anomalyType);
  }
  
  if (insight.hasRecommendation) {
    Serial.print("建议: ");
    Serial.println(insight.recommendationText);
  }
  
  Serial.println("----------------");
}